package com.sf.bluetoothserverdemo;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

public class MainActivity extends AppCompatActivity {
    Button startBleBtn, searchBtn, stopSearchBtn,waitConnectBtn,stopSocketBtn,sendBtn;
    ListView lv;
    TextView  stateTv,contentTv;
    private static final int REQUEST_ENABLE_BT = 1;
    private BluetoothAdapter defaultBleAdapter;
    private List<BluetoothDevice> deviceList;
    private final String lockName = "BOLUTEK";
    private List<String> deviceNames;
    private UUID  uuid= UUID.randomUUID();
    private String  name="bluetooth";
    AsServerAcceptThread  serverAcceptThread;
    AsClientConnectThread  clientConnThread;

    private int mState;
    private int mNewState;

    public static final int STATE_NONE = 0;
    public static final int STATE_LISTEN = 1;
    public static final int STATE_CONNECTING = 2;
    public static final int STATE_CONNECTED = 3;

    private static final String NAME_SECURE = "BluetoothChatSecure";
    private static final UUID MY_UUID_SECURE =
            UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    private static final UUID MY_UUID_INSECURE =
            UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //广播
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(mReceiver, filter);
        //view init
        startBleBtn = findViewById(R.id.start_btn);
        searchBtn = findViewById(R.id.search_btn);
        stopSearchBtn = findViewById(R.id.stop_search);
        waitConnectBtn = findViewById(R.id.wait_connect);
        stopSocketBtn = findViewById(R.id.stop_connect);
        sendBtn = findViewById(R.id.send_content_btn);

        lv = findViewById(R.id.ble_list);
        stateTv = findViewById(R.id.connect_state);
        contentTv = findViewById(R.id.connect_content);
        stateTv.setText("状态："+"未连接");
        //init
        defaultBleAdapter = BluetoothAdapter.getDefaultAdapter();
        //listener
        startBleBtn.setOnClickListener(listener);
        searchBtn.setOnClickListener(listener);
        waitConnectBtn.setOnClickListener(listener);
        stopSearchBtn.setOnClickListener(listener);
        stopSocketBtn.setOnClickListener(listener);
        stopSocketBtn.setOnClickListener(listener);
        sendBtn.setOnClickListener(listener);
        lv.setOnItemClickListener(itemClickListener);

    }



    private AdapterView.OnItemClickListener  itemClickListener=new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            defaultBleAdapter.cancelDiscovery();
            BluetoothDevice device =  deviceList.get(position);
            startClientConnet(device);  //开始客户端连接  ,通过mac地址进行连接

        }
    };
    private View.OnClickListener listener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.start_btn:
                    open();
                    break;
                case R.id.search_btn:
                    search();
                    startServerWaitConnect();
                    break;
                case R.id.wait_connect:
//                    startServerWaitConnect();
                    break;
                case R.id.stop_connect:
                    stopSocketConn();
                    break;
                case R.id.stop_search:
                    defaultBleAdapter.cancelDiscovery();
                    break;
                case R.id.send_content_btn:
                    sendMsgToRemoteDevice("this is test");
                    break;


            }
        }
    };

    /**
     * 停止sockts
     */
    private void  stopSocketConn(){
        if(serverAcceptThread!=null){
            serverAcceptThread.cancel();
            serverAcceptThread=null;
        }
        if(clientConnThread!=null){
            clientConnThread.cancel();
            clientConnThread=null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);

    }

    /**
     * 开启服务端sockt线程
     */
    private void  startServerWaitConnect(){
        if(clientConnThread!=null){
            clientConnThread.cancel();
            clientConnThread=null;
        }

        if(serverAcceptThread!=null){
            serverAcceptThread.cancel();
            serverAcceptThread=null;
        }
        serverAcceptThread=new AsServerAcceptThread(); //启动accept线程
        serverAcceptThread.start();
    }

    /**
     * 开启客户端sockt线程
     * @param device
     */
    private void  startClientConnet(BluetoothDevice device){
        if(clientConnThread!=null){
            clientConnThread.cancel();
            clientConnThread=null;
        }
        if(clientConnThread!=null){
            clientConnThread.cancel();
            clientConnThread=null;
        }
        clientConnThread=new AsClientConnectThread(device);
        clientConnThread.start();
        //此处更新UI。 连接某某设备中
        connectionDoing();
    }
    /**
     * 开启蓝牙
     */

    private void open() {
        if (defaultBleAdapter == null) {
            Log.d("ble", "不支持蓝牙");
        }
        if (!defaultBleAdapter.isEnabled()) {
            defaultBleAdapter.enable();
        }
        Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); //请求启用蓝牙
        enable.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 3600); //可见时间
        startActivityForResult(enable, REQUEST_ENABLE_BT);

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) { //ble  success
            Toast.makeText(this, "开启蓝牙成功", Toast.LENGTH_SHORT).show();
        } else if (requestCode == RESULT_CANCELED) { //ble fail
            Toast.makeText(this, "开启蓝牙失败", Toast.LENGTH_SHORT).show();

        }
    }

    private void search() {
        deviceList = new ArrayList<BluetoothDevice>();
        deviceNames = new ArrayList<String>();
        Set<BluetoothDevice> pairedDevices = defaultBleAdapter.getBondedDevices();//已配对的已知设备
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                deviceNames.add("name="+device.getName()+" mac="+device.getAddress());
                deviceList.add(device);
            }
        }
        showDevices();
        defaultBleAdapter.startDiscovery();
    }

    /**
     * 接收每台发现的设备的相关信息
     */
    private  BroadcastReceiver mReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_FOUND.equals(action)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                deviceNames.add("name="+device.getName()+" mac="+device.getAddress());
                deviceList.add(device);
            }
            notifyDevices();
        }
    };

    private boolean isLock(BluetoothDevice device) {
        boolean isLockName = (device.getName()).equals(lockName);
        boolean isSingleDevice = deviceNames.indexOf(device.getName()) == -1;
        if(TextUtils.isEmpty(device.getName())){
            isLockName=false;
        }
        return isLockName && isSingleDevice;
    }


    ArrayAdapter<String> lvAapter;

    private void showDevices() {
        lvAapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceNames);
        lv.setAdapter(lvAapter);
    }

    private void  notifyDevices(){
        lvAapter.notifyDataSetChanged();
    }

    private void  closeBle(){
        defaultBleAdapter.disable();
    }

    /**
     * 作为client 连接别的设备
     */
    private class AsClientConnectThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final BluetoothDevice mmDevice;

        public AsClientConnectThread(BluetoothDevice device) {
            BluetoothSocket tmp = null;
            mmDevice = device;
            try {
                tmp = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE);
            } catch (IOException e) { }
            mmSocket = tmp;
        }

        public void run() {
            defaultBleAdapter.cancelDiscovery();

            try {
                mmSocket.connect(); //发起连接，阻塞式连接，知道成功或者失败才返回
            } catch (IOException connectException) {
                try {
                    mmSocket.close();
                } catch (IOException closeException) { }

                connectionFailed();// 连接失败
                return;
            }
            synchronized (this) {
                clientConnThread = null; //重置 客户端发起连接的线程
            }

            manageConnectedSocket(mmSocket,mmDevice);//启动传输数据的线程
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }
    }

    /**
     *作为服务端等待被连接
     */
    private class AsServerAcceptThread extends Thread {
        private final BluetoothServerSocket mmServerSocket;

        public AsServerAcceptThread() {
            BluetoothServerSocket tmp = null;
            try {
                tmp = defaultBleAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, MY_UUID_SECURE);//获取 BluetoothServerSocket
            } catch (IOException e) { }
            mmServerSocket = tmp;
            mState = STATE_LISTEN; //开启服务端监听中
        }

        public void run() {
            BluetoothSocket socket = null;
//            while (true) {
            while (true) {
                try {
                    socket = mmServerSocket.accept(); //开始侦听客户端发过来的连接请求
                } catch (IOException e) {
                    break;
                }
                if (socket != null) { //这个地方有可能需要同步
                    try {
                        manageConnectedSocket(socket,socket.getRemoteDevice());//启动用于传输数据的线程
                        mmServerSocket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }

        public void cancel() {
            try {
                mmServerSocket.close();
            } catch (IOException e) { }
        }
    }

    /**
     * 传输数据的线程. 通信线程
     */
    private class ConnectedThread extends Thread {
        private final BluetoothSocket mmSocket;
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;
        public ConnectedThread(BluetoothSocket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            mState = STATE_CONNECTED; //连接到了
            connectionSuccess(socket.getRemoteDevice());//此方法为更新UI的,连接成功
        }

        public void run() {
            byte[] buffer = new byte[1024];
            int bytes;

//            while (true) {
                while (true) {
                try {
                    bytes = mmInStream.read(buffer);
                    mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)//发送到activityHandler进行消息接收的监听
                            .sendToTarget();
                } catch (IOException e) {
                    Log.d("bluetooth","read接收数据端接收数据有异常");
                    connectionLost();
                    break;
                }
            }
        }

        /**
         *
         * 将数据发送到远程设备 。  线程开启后。   通过 activity往里传数据即可
         */
        public void write(byte[] bytes) {
            try {
                mmOutStream.write(bytes);
            } catch (IOException e) {
                Log.d("bluetooth","write发送端往外传数据有异常");
            }
        }

        public void cancel() {
            try {
                mmSocket.close();
            } catch (IOException e) { }
        }


    }

    /**
     * 通信连接丢失
     */
    private void connectionLost() {
        Message msg = mHandler.obtainMessage(CONNECT_LOST);
        mHandler.sendMessage(msg);

    }


    /**
     *启动通信的交换信息的socket线程
     */
    ConnectedThread  communicateThread;
    private void  manageConnectedSocket(BluetoothSocket  socket,BluetoothDevice device){
        if (clientConnThread != null) {
            clientConnThread.cancel();
            clientConnThread = null;
        }
        if(serverAcceptThread!=null){
            serverAcceptThread.cancel();
            serverAcceptThread=null;
        }
        if(communicateThread!=null){
            communicateThread.cancel();
            communicateThread=null;
        }
        communicateThread=new ConnectedThread(socket);
        communicateThread.start();
//        connectionSuccess(device);//此方法为更新UI的,连接成功
    }

    /**
     *
     */
    public static  final  String TOAST="TOAST";
    private void connectionFailed() {
        Message msg = mHandler.obtainMessage(CONNECT_FAILED);
        mHandler.sendMessage(msg);
    }

    private void connectionSuccess(BluetoothDevice  device) {
        Message msg = mHandler.obtainMessage(CONNECT_SUCCESS);
        Bundle bundle = new Bundle();
        bundle.putString("devicename", device.getName());
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }

    private void connectionDoing() {
        Message msg = mHandler.obtainMessage(CONNECT_DOING);
        mHandler.sendMessage(msg);
    }

    public static final int MESSAGE_READ=300;
    public static final int CONNECT_FAILED=500;
    public static final int CONNECT_LOST=501;
    public static final int READ_FAILED=502;
    public static final int WRITE_FAILED=503;

    public static final int CONNECT_SUCCESS=200;
    public static final int CONNECT_DOING=201;
    public static final int DATA=255;

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONNECT_LOST:
                    Toast.makeText(MainActivity.this, "连接丢失", Toast.LENGTH_LONG).show();
                    stateTv.setText("状态："+"连接丢失");
                    break;
                case CONNECT_FAILED:
                    Toast.makeText(MainActivity.this, "连接失败", Toast.LENGTH_LONG).show();
                    stateTv.setText("状态："+"连接失败");
                    break;
                case CONNECT_DOING:
                    stateTv.setText("状态："+"连接远程设备中");
                    break;
                case CONNECT_SUCCESS:
                    Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_LONG).show();
                    String  deviceName = msg.getData().getString("devicename");
                    stateTv.setText("状态："+"连接成功"+"和远程devicename="+deviceName+"连接成功");
                    break;
                case READ_FAILED:
                    Toast.makeText(MainActivity.this, "读取失败", Toast.LENGTH_LONG).show();
                    stateTv.setText("状态："+"读取失败,也就是接收消息时读取");
                    break;
                case WRITE_FAILED:
                    Toast.makeText(MainActivity.this, "写入失败", Toast.LENGTH_LONG).show();
                    stateTv.setText("状态："+"写入失败，也就是往外发送消息时写入");
                    break;
                case DATA:
                    Toast.makeText(MainActivity.this, msg.arg1 + "", Toast.LENGTH_LONG).show();
                    break;
                case MESSAGE_READ:
                    byte[] readBuf = (byte[]) msg.obj;
                    String readMessage = new String(readBuf, 0, msg.arg1);
                    contentTv.setText("信息："+readMessage);
                    break;
            }
        }
    };


    public  void   sendMsgToRemoteDevice(String  msg){
        if (mState!= STATE_CONNECTED) {
            Toast.makeText(this,"发送失败，未连接", Toast.LENGTH_SHORT).show();
            return;
        }
        if (msg.length() > 0) {
            byte[] send = msg.getBytes();
            communicateThread.write(send);

        }
    }
}

